home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 1
/
Nebula One.iso
/
Mail
/
MailEnclosure
/
Source.v0.15
/
ModuleMgr.m
< prev
next >
Wrap
Text File
|
1995-06-12
|
5KB
|
214 lines
#import "ModuleMgr.h"
#import "TokenString.h"
#import "Directory.h"
#import "NXGets.h"
@implementation ModuleMgr
- initForPaths: (const char *)aPath fileType: (const char *)aType
{
[super initKeyDesc: "*"];
paths = [[StringStorage alloc] init: aPath];
if(!*[paths stringValue])
{
[paths setStringValue: "/LocalLibrary/%s:~/Library/%s"];
[paths replaceSubstring: "%s" with: [NXApp appName]];
[paths replaceSubstring: "%s" with: [NXApp appName]];
}
NXLogError("Looking for modules in %s", [paths stringValue]);
fileType = [[StringStorage alloc] init: aType];
features = (Protocol *)0;
[self loadModules];
return self;
}
- setFeatures: (Protocol *) aProtocol
{
features = aProtocol;
return self;
}
- loadModules
{
int cnt;
const char *aPath;
id modules = [[Directory alloc] init];
id path = [[TokenString alloc] init: [paths stringValue]];
id pattern = [[StringStorage alloc] init: "*."];
[path setSeparator: ':'];
[pattern appendStringValue: [fileType stringValue]];
while(aPath = [path popStringValue])
{
[modules setPath: aPath];
if([modules count] && ( cnt = [modules select: [pattern stringValue]]))
{
int x;
id sendModules = [modules selectedFiles];
id modulePath;
char *moduleName;
/*
* Create a hash of the modules. Use the name and path until the module is needed
* And the the path will be converted to a bundle.
*/
for(x = 0; x < cnt; x++)
{
NX_MALLOC(moduleName, char,[[sendModules objectAt: x] count]);
strcpy(moduleName, [[sendModules objectAt: x] stringValue]);
modulePath = [[StringStorage alloc] init: [modules path]];
[modulePath appendCharValue: '/'];
[modulePath appendStringValue: moduleName];
moduleName[strlen(moduleName) - (strlen([fileType stringValue]) + 1)] = (char)0; /* clip off .sndO */
[self insertKey: moduleName value: modulePath];
if(![self isKey: moduleName])
NXLogError("Hash failed\n");
}
}
}
[pattern free];
[modules free];
[path free];
return self;
}
- loadFileType: (const char *)aType
{
return self;
}
- free
{
[paths free];
[fileType free];
return [super free];
}
- getModule: (const char *)moduleName
{
id bundle = (id)[self valueForKey: moduleName];
id loaded, primeClass;
char modulePath[MAXPATHLEN];
char *newKey;
if(!bundle)
{
const char *aKey;
[self initState];
NXLogError("Could not find hash entry: (%s)\n", moduleName);
while (aKey = [self nextKey]);
NXLogError("moduleName: %s", aKey);
return nil;
}
if([bundle isKindOf: [NXBundle class]])
return bundle;
if(![bundle isKindOf: [StringStorage class]])
{
NXLogError("Hash stored bad item...");
return nil;
}
/* Bundle was not yet loaded - do so. */
NXLogError("Need to load: %s", [bundle stringValue]);
loaded = [[NXBundle alloc] initForDirectory: [bundle stringValue]];
if(!loaded)
{
NXLogError("failed to load\n");
return nil;
}
/* insert the real bundle into the hash now to replace the place holder */
NX_MALLOC(newKey, char, strlen(moduleName)); /* allocate another key - this is a bug in HashTable I feel */
strcpy(newKey, moduleName);
[self insertKey: newKey value: loaded];
[bundle free]; /* free up the path/place holder */
bundle = loaded;
/*
* Before we resolve the symbols in the bundle see if it needs any
* other bundles loaded as ancestors.
*/
if([bundle getPath: modulePath forResource: "inheritance" ofType: ""])
{
NXStream *sp;
char parentsBuf[128];
const char *parent;
id parents;
sp = NXMapFile(modulePath, NX_READONLY);
if(!sp)
{
NXLogError("Couldn't open %s\n", [bundle stringValue]);
return nil;
}
NXGets(parentsBuf, 128, sp);
NXClose(sp);
/* Get known parrents and load them */
parents = [[TokenString alloc] init: parentsBuf];
while(parent = [parents popStringValue])
if(![self getModule: parent])
{
NXLogError("Ancestor failed to load...\n");
return nil;
}
[parents free];
}
if(!(primeClass = [bundle principalClass]))
{ /* make rld resolve names */
NXLogError("Corruoted bundle: %s\n", moduleName);
return nil;
}
if(features)
{
if(![primeClass conformsTo: features])
{
NXLogError("Bundle's principal class does not conform to %s protocol.", [features name]);
return nil;
}
}
return bundle;
}
- (NXHashState) initState
{
state = [super initState];
return state;
}
- (const char *)nextKey
{
static const void *key, *value;
if([self nextState: &state key: &key value: &value])
return (const char *)key;
else
return (const char *)0;
}
@end